#!/usr/bin/env ruby

#--
# Created by Matt Todd on 2007-11-10.
# Copyright (c) 2007 The HUB, Clayton State University. All rights reserved.
#++

# dependencies

require 'rubygems'
require 'logger'
require 'uri'
require 'json'
require 'digest/md5'
require 'mongrel'

# module

module Aurora
  module Server
    
    # Base
    class Base
      
      #--
      # constants and attributes
      #++
      
      DEFAULTS = {
        :log_file => '/var/log/aurora.server.log',
        :log_level => Logger::ERROR
      }
      
      attr_accessor :options, :uri, :logger, :processes
      
      #--
      # class methods
      #++
      
      # Starts the server listening on the port specified
      def initialize(uri, options = {})
        # setup options
        @options = DEFAULTS.merge(options)
        @uri = URI.parse(uri)
        @logger = Logger.new(@options[:log_file])
        @logger.level = @options[:log_level]
        
        @logger.info 'Starting Aurora Authentication Server...'
        
        # setup authentication handlers
        @logger.info 'Loading processes...'
        yield self, @uri, @logger
        @logger.info 'done.'
        
        # setup server
        @logger.info 'Starting HTTP Server and setting up HTTP Handler...'
        serv = Aurora::Server::Server.new(@uri.host, @uri.port)
        serv.register('/', Aurora::Server::Handler.new(self))
        @logger.info 'done. Running now.'
        serv.run.join
      end
      
      #--
      # instance methods
      #++
      
      def parse_credentials(body)
        ['mtodd', 'test']
      end
      
      def authenticate(&block)
        add_process(:authenticate, block)
      end
      
      def method_missing(name, *args, &block)
        add_process(name, block)
      end
      
      private
      
      # Adds process 
      def add_process(name, proc)
        @processes ||= {}
        @processes[name] = proc
      end
      
    end
    
    # Server
    class Server < Mongrel::HttpServer
      #
    end
    
    # Handler
    class Handler < Mongrel::HttpHandler
      
      #--
      # constants and attributes
      #++
      
      attr_accessor :serv
      
      #--
      # class methods
      #++
      
      # Stores a reference to the Base server to access the processes (procs
      # which define auth functionality) and then returns to the super
      def initialize(serv)
        @serv = serv
        @serv.logger.info 'Loading Handler.'
        super()
      end
      
      #--
      # instance methods
      #++
      
      # Generic request processor (Mongrel hook)
      def process(request, response)
        @serv.logger.info 'Request received.'
        
    		# parse out username and password and call the authenticate method
    		@serv.logger.info request.body
    		user, pass = *Aurora::Server::Base.parse_credentials(request.body)
    		response = @serv.processses[:authenticate].call(user, pass)
    		
    		# prepare response
    		if response.is_a? Aurora::Server::Token then
      		# success
      		code = 200
      	else
      	  # failure
      	  code = 200
    	  end
    	  
    	  # send response
    	  response.start(code) do |head, out|
      		head["Content-Type"] = "application/json"
      		out.write(result.to_json)
      	end
      end
      
    end
    
    # Token
    class Token
      
      #--
      # constants and attributes
      #++
      
      attr_accessor :token, :lifetime
      
      #--
      # class methods
      #++
      
      # Takes the lifetime of the token
      def initialize(user, pass, lifetime=5*60)
        @lifetime = lifetime
        @token = Digest::MD5.hexdigest("#{user}:#{pass}").split(/(....)/)[1..-1].map{|node|node="-" if node==""; node}.to_s.upcase
        
        @@tokens ||= []
        @@tokens << self
      end
      
      # Creates JSON format of Token
      def to_json
        {
          :token => @token,
          :lifetime => @lifetime
        }.to_json
      end
      
    end
    
  end
end
